package com.yuchao.springboot.service;

import com.yuchao.springboot.exception.RetryException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * @description:
 * @author: xingyuchao
 * @date: 2019-11-26
 */
@Service
@Slf4j
public class RetryServiceImpl implements RetryService {

    /**
     *
     * value：抛出指定异常才会重试
     * include：和value一样，默认为空，当exclude也为空时，默认所有异常
     * exclude：指定不处理的异常
     * maxAttempts：最大重试次数，默认3次
     * backoff：重试等待策略，默认使用@Backoff，@Backoff的value默认为1000L，表示延迟1s重试
     * multiplier（指定延迟倍数）默认为0，表示固定暂停1秒后进行重试，如果把multiplier设置为1.5，则第一次重试为2秒，第二次为3秒，第三次为4.5秒。
     */
    @Override
    @Retryable(include = {RetryException.class}, maxAttempts = 2, backoff = @Backoff(delay = 1000l))
    public String retry() {

        RetryException retryException = null;
        try {
            double v = Math.random() * 100;
            int random = (int)v;

            //偶数
            if((random & 1) == 0){
                retryException = RetryException.builder().code("9999").message("连接超时").build();
                throw retryException;
            }
            return "ok";
        } catch (RetryException e) {
            throw retryException;
        }
    }


    /**
     * 当重试耗尽时，RetryOperations可以将控制传递给另一个回调，
     * 即RecoveryCallback。Spring-Retry还提供了@Recover注解，
     * 用于@Retryable重试失败后处理方法，此方法里的异常一定要是@Retryable方法里抛出的异常，
     * 否则不会调用这个方法。
     * @param e
     * @return
     */
    @Recover
    public String recover(RetryException e) {
        log.info(e.getMessage());
        return "6";
    }
}